const request = require('base')
const synctool = require('synctool')
const OpenCC = require('opencc-js')
const pinyin = require('chinese-to-pinyin')
const {cilinzhengyun, pingshuiyun, tongya} = require('./psy')

// 默认的繁体字类型
const TType = 'hk'
// 允许的符号。如果要新增符号，需对该符号指定一个平仄值。、是0；，；是3；。？！是4；\n是5
const symbol = ['，', '；', '。', '！', '？', '\n']

// 简繁文字转换
const convert = ({text, from, to}) => {
	if (to === 'p') {
		return text
	}
	const converter = OpenCC.Converter({ from, to })
	return converter(text)
}

module.exports = {
	_before: function () {
		request.handleBefore(this)
	},
	
	_after(error, result) {
		return request.handleAfter(this, error, result)
	},
	/**
	 * 转为正体字
	 * 综合简繁之后得到的更优秀的文字
	 */
	proper(params) {
		const {text, from = 'cn', to = 'p'} = params
		return new Promise((resolve, reject) => {
			resolve(request.getResult({data: convert({text, from, to}), original: text, from, to}))
		})
	},
	// 转为简体字
	simplify(params) {
		const {text, from = TType, to = 'cn'} = params
		return new Promise((resolve, reject) => {
			resolve(request.getResult({data: convert({text, from, to}), original: text, from, to}))
		})
	},
	// 转为繁体字
	traditional(params) {
		const {text, from = 'cn', to = TType} = params
		return new Promise((resolve, reject) => {
			if (0) { // 百度翻译api报未知错误，应该要去注册使用
				request.fetchUrl('https://fanyi.baidu.com/v2transapi', { 
					headers: {
						'Content-Type': 'application/x-www-form-urlencoded',
					},
					method: 'POST',
					data: `from=cht&to=zh&query=${encodeURIComponent(text)}`
				}).then(res => {
					var result
					const {errmsg, trans_result} = res.data
					if (errmsg) {
						reject(request.getError(errmsg))
					} else {
						if (trans_result && trans_result.data && trans_result.data.length > 0) {
							res = trans_result.data[0].dst
						} else {
							res = ''
						}
						resolve({data: {res, text}})
					}
				}).catch(reject)
			} else {
				resolve(request.getResult({data: convert({text, from, to}), original: text, from, to}))
			}
		})
	},
	
	/**
	 * 获取一段文字的信息
	 * 以平水韵的基准
	 * 返回格式是数组，每一个元素表示每一个文字对应的平仄
	 * 	o：原始文字
	 * 	s：简体字
	 * 	t：繁体字
	 * 	p：正体字
	 * 	py：该字的拼音
	 *  sd：该字的声调
	 * 	pz：1平声；2仄声；0顿号（一般省略，在前端如果前面有一个字以上不省略）；-1逗号（包含分号）；-2句号（包含感叹号疑问号）；-3换行
	 * 	value：1阴平；2阳平；3上声；4去声；5入声
	 * 	yp：该字所属的平水韵部
	 * 	yc：该字所属的词林正韵韵部
	 * 	ym：该字拼音的主韵母
	 * 	y：该字所属的韵部 - 来自于psy.tongya
	 * 
	 * 1，规范文字，包含阿拉伯数字全部转为汉字、标点符号全部转为全角符号。非汉字及标点符号全部作废
	 * 2，获取每一个字的拼音以及声调
	 * 3，获取每一个字的简体字、繁体字和正体字
	 * 
	 * 允许的文字类型
	 * 1，正常汉字
	 * 2，阿拉伯数字 - 会被替换为中文数字
	 * 3，全角标点符号 - 有对应的半角符号会被替换为全角符号
	 * 4，换行符\n
	 */
	character(params) {
		const regex = /[\u4e00-\u9fa5\u3000-\u303f\uff00-\uffef]/; // 汉字阿拉伯数字及标点符号
		const numbers = '0123456789' // 数字要转化为中文
		/**
		 * text：需要特别处理的文字
		 * title：转化为原文、简体字、繁体字、正体字。返回 内容有一个专门的title对象: {s: '', t: '', p: '', o: ''}
		 * 
		 * sType：简体字类型
		 * tType：繁体字类型
		 */
		var {text, title, sType = 'cn', tType = TType} = params
		const arr = []
		var num = ''
		for (let i = 0; i < text.length; i++) {
			var t = text[i]
			switch (t){
				case ' ': // 所有空格替换为全角空格
					t = '　';
					break
				case '\\':
				case '/':
					t = '、'
					break;
				case ';':
					t = '；'
					break;
				case ',':
				case '|':
					t = '，'
					break;
				case '.':
					t = '。'
					break;
				case '!':
					t = '！'
					break;
				case '?':
					t = '？'
					break;
				default:
					break;
			}
			if (regex.test(t) || symbol.includes(t) || numbers.indexOf(t) > -1) { // 必须是中文阿拉伯数字以及全角字符
				if (numbers.indexOf(t) > -1) {
					num += t
				} else {
					if (num) { // 阿拉伯数字全部转为汉字。并且删除前面的几项，重新添加
						var res = synctool.number.convertToChinaNum(num)
						arr.splice(i - num.length, num, ...res.split(''))
					}
					num = ''
				}
				arr.push(t)
			}
		}
		text = arr.join('')
		// 将通过pinyin获取的数据的标点符号一起添加进来
		const handlePinyin = (string) => {
			const temArr = []
			var str = ''
			for (let i = 0; i < string.length; i++) {
				if (string[i] === ' '){
					if (str) {
						temArr.push(str)
						str = ''
					}
				} else if (symbol.includes(string[i])) {
					if (str) {
						temArr.push(str)
						str = ''
					}
					temArr.push(string[i])
				} else {
					str += string[i]
				}
			}
			return temArr
		}
		const py = handlePinyin(pinyin(text, {keepRest: true})) // 获取拼音数组
		const pyn = handlePinyin(pinyin(text, {removeTone: true, keepRest: true})) // 略去声调的拼音
		const sd = handlePinyin(pinyin(text, {toneToNumberOnly: true, keepRest: true})) // 获取声调数组
		const simplify = convert({text, to: sType, from: tType}) // 获取简体字
		const traditional = convert({text, to: tType, from: sType}) // 获取繁体字
		const proper = convert({text, to: 'p', from: sType}) // 获取正体字
		if (title) {
			var title_s = convert({text: title, to: sType, from: tType}), // 获取简体字
				title_t = convert({text: title, to: tType, from: sType}), // 获取繁体字
				title_p = convert({text: title, to: 'p', from: sType}) // 获取正体字
			title = {o: title}
			if (title_s !== title.o) {
				title.s = title_s
			}
			if (title_t !== title.o) {
				title.t = title_s
			}
			if (title_p !== title.o) {
				title.p = title_s
			}
		}
		const yarr = Object.keys(tongya) // 通押的情况
		const getZym = (pystr) => {
			// 获取该字完整的韵母结构。没有ü，而是v
			if (symbol.includes(pystr)) {
				return undefined
			}
			var yunmu = pystr && pystr.replace(/^[bpmfdtnlgkhjqxrzcsyw]/, '').replace(/^h/, '')
			/**
			 * 通过韵母得到主韵母
			 */
			var zym = yunmu
			switch (yunmu){
				case 'iu':
					zym = 'ou'
					break
				case 'ui':
					zym = 'ei'
					break
				case 'un':
					zym = 'en'
					break
				default:
					if (yunmu && yunmu.length > 1) { // 首韵母是i、u、ü、v的，要排除in、un、vn
						if (['i', 'u', 'v'].indexOf(yunmu.substr(0, 1)) > -1 && yunmu.substr(1, 1) !== 'n') {
							zym = yunmu.substr(-1 * yunmu.length + 1)
						}
					}
					break;
			}
			return zym
		}
		// 逐字判断
		for (let i = 0; i < text.length; i++) {
			var value = undefined, pz = undefined, ym = undefined, yp = undefined, yc = undefined, ys = undefined, y = undefined
			const o = text[i]
			switch (o){
				case '、':
					pz = 0
					break;
				case '，':
				case '；':
					pz = -1
					break;
				case '。':
				case '！':
				case '？':
					pz = -2
					break;
				case '\n':
					pz = -3
					break;
				default:
				{
					/**
					 * 1，查询在平水韵中的分布
					 * 多音字如果有多个韵部分布，默认是第一个，则根据具体韵部的第一个字的主韵母比对
					 */
					var temp = undefined
					pingshuiyun.forEach(item1 => {
						item1.child.forEach(item2 => {
							item2.child.forEach(item3 => {
								if (item3.child.indexOf(o) > -1) {
									if (temp) { // 由平水韵原文中[]内的字得出正确的读音
										var ta = item3.text.split(o)
										delete ta[0]
										ta = ta.join(o)
										var ciyu = ta.split(']')[0].split('[').pop()
										if (ciyu) {
											var index = ciyu.indexOf(o)
											var piny = pinyin(ciyu, {removeTone: true, keepRest: true}).split(' ')
											if (piny[index] === pyn[i]) {
												// 就是要找的韵部
											} else {
												return
											}
										} else {
											return
										}
									}
									temp = {
										value: parseInt(item2.value),
										pz: parseInt(item1.value),
										yp: item3.label,
										yc: item3.clzy
									}
								}
							})
						})
					})
					if (temp) {
						value = temp.value
						pz = temp.pz
						yp = temp.yp
						yc = temp.yc
					}
				}
					break;
			}
			const obj = {
				o, // 该字本身。如果简体字繁体字正体字与本字相同，则不显示
				s: simplify[i], // 简体字
				t: traditional[i], // 繁体字
				p: proper[i], // 正体字。暂无
				py: py[i], // 该字的拼音
				sd: parseInt(sd[i]) || undefined, // 该字的声调
				value, // 1阴平；2阳平；3上声；4去声；5入声
				pz, // 1平声；2仄声；3逗号（包含分号）；4句号（包含感叹号疑问号）；0顿号（一般省略，在前端如果前面有一个字以上不省略）；
				ym, // 该字所属的主韵母
				yp, // 该字所属的平水韵部
				yc, // 该字所属的词林正韵部
				y // 该字所属的通用韵部
			}
			if (obj.p && obj.p !== obj.o)  {
				// 存在正体字
			} else {
				delete obj.p
			}
			if (obj.s === obj.o) {
				delete obj.s
			}
			if (obj.t === obj.o) {
				delete obj.t
			}
			// 获取该字音节的主韵母
			obj.ym = getZym(pyn[i])
			for (let j = 0; j < yarr.length; j++) {
				if (tongya[yarr[j]].includes(obj.ym)) {
					obj.y = yarr[j]
					break;
				}
			}
			arr[i] = obj
		}
		return Promise.resolve(request.getResult({data: arr, title}))
	}
}
